package com.lincoln.redis.server;

import com.alibaba.fastjson.JSONObject;
import com.lincoln.bean.ApiCode;
import com.lincoln.bean.ApiCodeException;
import com.lincoln.config.ExpectionHandle;
import com.lincoln.redis.server.config.RedisConfig;
import com.lincoln.redis.server.config.ServerConfig;
import com.lincoln.redis.server.entity.User;
import com.lincoln.redis.server.service.UserService;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * 启动类
 *
 * @author lincoln
 */
@SpringBootApplication
@EnableAspectJAutoProxy
@RestController
@RequestMapping("/")
@CrossOrigin
public class RedisServerApplication {
    private static Logger logger = LoggerFactory.getLogger(RedisServerApplication.class);

    @Bean
    public ExpectionHandle expectionHandle() {
        return new ExpectionHandle();
    }

    /**
     * 注入jedis连接池
     */
    @Bean
    public JedisPool jedisPoolConfig(RedisConfig redisConfig) {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(redisConfig.getMaxTotal() <= 0 ? 50 : redisConfig.getMaxTotal());
        poolConfig.setMinIdle(redisConfig.getMinIdle() <= 0 ? 10 : redisConfig.getMinIdle());
        poolConfig.setMaxIdle(redisConfig.getMaxIdle() <= 0 ? 30 : redisConfig.getMaxIdle());
        JedisPool pool = new JedisPool(poolConfig, redisConfig.getIp(), redisConfig.getPort());
        return pool;
    }

    public static void main(String[] args) {
        SpringApplication.run(RedisServerApplication.class, args);
    }

    @Autowired
    UserService userService;

    @PostMapping("/login")
    public ApiCode login(String username, String password) throws Exception {
        if (username == null || "".equals(username) || password == null || "".equals(password)) {
            throw new ApiCodeException(10001);
        }
        User user = userService.findByName(username);
        if (user == null) {
            throw new ApiCodeException(11002);
        }
        return ApiCode.build(dispathOauth(username, password));
    }

    @PostMapping("/logout")
    public ApiCode logout(String username, String password) throws Exception {
        return ApiCode.build(true);
    }

    @PostMapping("/refresh")
    public ApiCode refresh(String refreshToken) throws Exception {
        if (refreshToken == null || "".equals(refreshToken)) {
            throw new ApiCodeException(10001);
        }
        return ApiCode.build(refreshToken(refreshToken));
    }


    @Autowired
    ServerConfig serverConfig;

    /**
     * 代理请求token
     *
     * @param username
     * @param password
     * @return
     * @throws Exception
     */
    public Map<String, String> dispathOauth(String username, String password) throws Exception {
        URL url = new URL("http://localhost:" + serverConfig.getPort() + "/oauth/token?clientId=redis-server&grant_type=password&clientSecret=123456&scope=redis-server&username=" + username + "&password=" + password);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setDoInput(true);
        connection.setUseCaches(false);

        String plainCredentials = "redis-server:123456";
        String base64Credentials = new String(Base64.encodeBase64(plainCredentials.getBytes()));
        connection.setRequestProperty("Authorization", "Basic " + base64Credentials);
        String content;
        try {
            InputStream inputStream = connection.getInputStream();
            byte[] bytes = new byte[inputStream.available()];
            inputStream.read(bytes);
            content = new String(bytes);
            inputStream.close();
            connection.disconnect();
        } catch (IOException e) {
            logger.error("{}", e);
            Map<String, String> res = new HashMap<>(1);
            res.put("msg", "权限错误!");
            return res;
        }
        try {
            JSONObject jsonObject = JSONObject.parseObject(content);
            Map<String, String> res = new HashMap<>(2);
            res.put("access_token", jsonObject.getString("access_token"));
            res.put("refresh_token", jsonObject.getString("refresh_token"));
            return res;
        } catch (Exception e) {
            logger.error("string转json失败", content);
            Map<String, String> res = new HashMap<>(1);
            res.put("msg", "权限错误!");
            return res;
        }
    }

    /**
     * 代理请求token
     *
     * @param refreshToken
     * @return
     * @throws Exception
     */
    public Map<String, String> refreshToken(String refreshToken) throws Exception {
        URL url = new URL("http://localhost:" + serverConfig.getPort() + "/oauth/token");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);

        String out = "clientId=redis-server&grant_type=refresh_token&clientSecret=123456&scope=redis-server&refresh_token=" + refreshToken;

        String plainCredentials = "redis-server:123456";
        String base64Credentials = new String(Base64.encodeBase64(plainCredentials.getBytes()));
        connection.setRequestProperty("Authorization", "Basic " + base64Credentials);

        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(out.getBytes());
        outputStream.flush();
        outputStream.close();

        try {
            InputStream inputStream = connection.getInputStream();
            byte[] bytes = new byte[inputStream.available()];
            inputStream.read(bytes);
            String content = new String(bytes);
            inputStream.close();
            connection.disconnect();
            JSONObject jsonObject = JSONObject.parseObject(content);
            Map<String, String> res = new HashMap<>(2);
            res.put("access_token", jsonObject.getString("access_token"));
            res.put("refresh_token", jsonObject.getString("refresh_token"));
            return res;
        } catch (IOException e) {
            Map<String, String> res = new HashMap<>(1);
            res.put("msg", "权限错误!");
            return res;
        }
    }

}

